/*
运行使用：RUST_BACKTRACE=1 cargo run
一些错误可以通过Result获取错误！避免崩溃。
*/
use std::fs::File;
use std::io::Read;
use std::io::ErrorKind;
fn main() {
    {
        {
            // let f = File::open("hello.txt");
            // let f = match f {
            //     Ok(file) => file,
            //     Err(error) => {
            //         panic!("Problem opening the file: {:?}", error)
            //     },
            // };
        }
        {
            let f = File::open("hello.txt");
            let f = match f {
                Ok(file) => {
                    // std::fs::File
                    println!("[{},{}]open ok:{:?},{}", file!(), line!(), file, type_str(&file));
                }
                Err(error) => {
                    println!("[{},{}]open fail,{}", file!(), line!(), error);
                    // 没有返回值。
                    // panic!("Problem opening the file: {:?}", error)
                },
            };
            println!("[{},{}]open result:{:?},{}", file!(), line!(), f, type_str(&f));//值和类型都为空。
        }
    }
    {
        match read_user_file1() {
            Ok(tmpstr) => println!("[{},{}]read result:{}", file!(), line!(), tmpstr),
            Err(tmperr) => println!("[{},{}]read result:{:?}", file!(), line!(), tmperr),
        };
    }
    {
        if let Ok(tmpstr) = read_user_file2() {
            println!("[{},{}]read result:{}", file!(), line!(), tmpstr);
        } else {
            println!("[{},{}]read fail", file!(), line!());
        }
    }
    {
        let f = File::open("hello.txt");
        let f = match f {
            Ok(file) => file,
            Err(error) => match error.kind() {
                // 错误是没有找到，创建文件。
                // 可以将文件改为chmod 222 hello.txt，只写。这样就能导致崩溃。
                ErrorKind::NotFound => match File::create("hello.txt") {
                    Ok(fc) => fc,
                    Err(e) => panic!("Problem creating the file: {:?}", e),
                },
                other_error => panic!("Problem opening the file: {:?}", other_error),
            },
        };
        println!("[{},{}]open result:{:?},{}", file!(), line!(), f, type_str(&f));//值和类型都为空。
    }
    {
        // 第 13 章我们会介绍闭包（closure）。Result<T, E> 有很多接受闭包的方法，并采用 match 表达式实现。一个更老练的 Rustacean 可能会这么写：
        let f = File::open("hello.txt").unwrap_or_else(|error| {
            if error.kind() == ErrorKind::NotFound {
                File::create("hello.txt").unwrap_or_else(|error| {
                    panic!("Problem creating the file: {:?}", error);
                })
            } else {
                panic!("Problem opening the file: {:?}", error);
            }
        });
        println!("[{},{}]open result:{:?},{}", file!(), line!(), f, type_str(&f));//值和类型都为空。
    }
}

fn read_user_file1() -> Result<String, std::io::Error> {
    let mut f = File::open("hello.txt")?;//错误，直接返回错误
    let mut s = String::new();
    f.read_to_string(&mut s)?;//错误，直接返回错误
    Ok(s)
}

fn read_user_file2() -> Result<String, std::io::Error> {
    std::fs::read_to_string("hello.txt")
}


fn type_str<T>(_val: &T) -> & 'static str {
    std::any::type_name::<T>()
}
